// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: donggu

#include <cxxopts.hpp>

#include "coin2/base/config/app_config.h"
#include "coin2/base/config/args.h"
#include "coin2/base/log.h"
#include "coin2/base/time.h"
#include "coin2/exchange/base/executor/live_executor.h"
#include "coin2/exchange/base/executor/sync_executor.h"
#include "coin2/exchange/base/feed/subscriber.h"
#include "coin2/exchange/base/feed/update.h"
#include "coin2/feed/mgr/system.h"

using namespace coin2::exchange::base::symbology;
using namespace coin2::base::config;

// received_nano_time, venue_nano_time,msg_type,symbol,exchange, ask_p, ask_q, bid_p, bid_q,
// trade_p, trade_q
//                              book
class PrintingStrategy : public IFeedSubscriber {
  void onTradeFeed(const FeedUpdate& upd) override {
    auto& trade = upd.trade();
    printf(
        "%ld,%ld,trade,%s,%s,0,0,0,0,%f,%f\n",
        upd.timestamp(),
        trade.timestamp,
        upd.native_symbol().c_str(),
        ExchangeType_Name(upd.exchange()).c_str(),
        trade.price,
        trade.fill_qty);
  }
  void onBookFeed(const FeedUpdate& upd) override {
    auto& book = upd.book();
    printf(
        "%ld,%ld,book,%s,%s,%f,%f,%f,%f,0,0\n",
        upd.timestamp(),
        book.Timestamp(),
        upd.native_symbol().c_str(),
        ExchangeType_Name(upd.exchange()).c_str(),
        book.Ask0()->price,
        book.Ask0()->qty,
        book.Bid0()->price,
        book.Bid0()->qty);
  }
};

int main(int argc, char* argv[]) {
  google::InitGoogleLogging(argv[0]);

  DriverConfig app;

  cxxopts::Options opt("Feed Manager", "Run the feed subsystems");
  AddDriverOptions(&opt);
  AddIntervalOptions(&opt);
  AddProductOptions(&opt);

  auto res = opt.parse(argc, argv);
  ParseDriverOptions(res, &app);
  ParseIntervalOptions(
      res,
      app.mutable_feed()->mutable_common()->mutable_archive()->mutable_interval());
  ParseProductOptions(res, app.mutable_feed());

  LOG(INFO) << app.DebugString();

  PrintingStrategy printer;  // printer unused if feed-writer
  LiveAsyncExecutor lass(app.executor().live().raw_threads());
  ArchiveSyncExecutor aass(app.executor().archive());
  FeedSubsystemManager feed(app.feed(), &lass, &aass, &printer);
  printf(
      "received_nano_time,venue_nano_time,msg_type,symbol,exchange,ask_p,ask_q,bid_p,bid_q,trade_p,"
      "trade_q\n");

  if (lass.NumSystems() && aass.NumSystems()) {
    THROW() << "Both live and archive subsystem co-exist";
  } else if (lass.NumSystems() != 0U) {
    lass.Run();
  } else if (aass.NumSystems() != 0U) {
    aass.Run();
  }

  return 0;
}
